package com.song.user.controller;


import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.song.api.BaseController;
import com.song.api.controller.user.UserControllerApi;
import com.song.grace.result.GraceJSONResult;
import com.song.grace.result.ResponseStatusEnum;
import com.song.pojo.AppUser;
import com.song.pojo.bo.UpdateUserInfoBO;
import com.song.pojo.vo.AppUserVO;
import com.song.pojo.vo.UserAccountInfoVO;
import com.song.user.service.UserService;
import com.song.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

@RestController
public class UserController extends BaseController implements UserControllerApi {

    private static final Logger LOG = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    @Value("${server.port}")
    private String myPort;

    public GraceJSONResult globalFallback() {
        return GraceJSONResult.errorCustom(ResponseStatusEnum.SYSTEM_ERROR_GLOBAL);
    }


    @Override
    public GraceJSONResult getUserInfo(String userId) {

        // 0.判断userId不能为空
        if (StringUtils.isBlank(userId)) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.UN_LOGIN);
        }

        // 1.获取用户基本信息
        AppUserVO appUserVO = getBasicUserInfo(userId);

        // 2.查询用户的粉丝数，关注数
        appUserVO.setMyFansCounts(getCountsFromRedis(REDIS_WRITER_FANS_COUNTS + userId));
        appUserVO.setMyFollowCounts(getCountsFromRedis(REDIS_MY_FOLLOW_COUNTS + userId));

        return GraceJSONResult.ok(appUserVO);
    }

    @Override
    public GraceJSONResult getAccountInfo(String userId) {

        // 0.判断userId不能为空
        if (StringUtils.isBlank(userId)) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.UN_LOGIN);
        }

        // 1.根据userId查询用户信息
        AppUser user = getUser(userId);

        // 2.返回用户信息
        UserAccountInfoVO userAccountInfoVO = new UserAccountInfoVO();
        BeanUtils.copyProperties(user, userAccountInfoVO);

        return GraceJSONResult.ok(userAccountInfoVO);
    }

    @Override
    public GraceJSONResult updateUserInfo(@Valid UpdateUserInfoBO updateUserInfoBO) {

        // 1.执行更新操作
        userService.updateUserInfo(updateUserInfoBO);
        return GraceJSONResult.ok();
    }

    @HystrixCommand
    @Override
    public GraceJSONResult queryByIds(String userIds) {
        System.out.println("myPort= "+myPort);

        if (StringUtils.isBlank(userIds)) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.USER_NOT_EXIST_ERROR);
        }

        List<AppUserVO> publisherList = new ArrayList<>();
        List<String> userIdList = JsonUtils.jsonToList(userIds, String.class);
        for (String uid : userIdList) {
            // 获取用户基本信息
            AppUserVO appUserVO = getBasicUserInfo(uid);
            // 添加到发布者list
            publisherList.add(appUserVO);
        }

        return GraceJSONResult.ok(publisherList);
    }

    /**
     * 获取用户基本信息
     */
    private AppUserVO getBasicUserInfo(String userId) {

        // 1.根据userId查询用户信息
        AppUser user = getUser(userId);

        // 2.返回用户信息
        AppUserVO appUserVO = new AppUserVO();
        BeanUtils.copyProperties(user, appUserVO);

        return appUserVO;
    }

    /**
     * 获取用户
     *
     * @param userId
     * @return
     */
    private AppUser getUser(String userId) {
        // TODO 本方法后续待扩展
        // 1.查询判断redis中是否包含用户信息，如果包含，则查询后直接返回，就不去查询数据库了
        String userJson = redis.get(REDIS_USER_INFO + userId);
        AppUser user = null;
        if (StringUtils.isNotBlank(userJson)) {
            user = JsonUtils.jsonToPojo(userJson, AppUser.class);
        } else {
            user = userService.getUser(userId);
            // 2. 由于用户信息不怎么会变动，对于千万级别的网站，这类信息数据不会去查询数据库，完全可以把用户信息存入redis
            // 哪怕修改信息，也不会立马体现，这也是弱一致性，在这里有过期时间，比如1天以后，用户信息会更新到页面显示，或者缩短到1小时，都可以
            // 基本信息在新闻媒体类网站是属于数据一致性优先级比较低的，用户眼里看的主要以文章为主，至于文章是谁发的，一般来说不会过多关注
            redis.set(REDIS_USER_INFO + userId, JsonUtils.objectToJson(user));
        }
        return user;
    }

}
